Notice Feed (Outage Mirroring) ============================== Instead of emailing outages for manual posting, an ISP can host a public JSON feed that Issuetracker polls and mirrors into tracker notices automatically. The integration is configured per company on the Company administration page ("Notice API" section) — the ISP only has to host the feed described below and keep it current. How mirroring works ------------------- * Issuetracker polls the feed roughly every **5 minutes** (5–7 min with jitter). Serve fast, cacheable responses (e.g. ``Cache-Control: max-age=30``); responses must be HTTP 200, ``application/json`` and at most **1 MB**. * The feed is **full-state**: every currently open outage/maintenance must appear on every request. An entry that disappears from the feed is treated as resolved. * Entry ``id`` values must be **stable** for the lifetime of an event (and ideally never reused). The id is the mirroring key: content changes update the existing tracker notice, a resolving status or disappearance resolves it, and a reappearing id re-opens it. * **The feed is the source of truth.** Manual edits to a mirrored notice in the tracker are overwritten on the next poll. Support staff who need to suppress a mirrored notice should *hide* it — hidden notices keep receiving updates but stay hidden. * A fetch failure (timeout, non-200, invalid JSON) never changes anything in the tracker; only a successfully parsed feed is mirrored. An empty ``outages``/``maintenances`` list is valid and resolves everything. Authentication -------------- The feed may be public, or protected by either a **static header** (name + value, e.g. ``X-Api-Key``) or **HTTP Basic** credentials. Both are configured tracker-side in the company's Notice API section. Feed schema ----------- :: { "as_of": "2026-08-20T21:39:24Z", "status_summary": "major", "outages": [ { "id": "EVT-003081", "status": "investigating", "started_at": "2026-08-18T06:52:40Z", "etr": "2026-08-19T14:17:45Z", "public_text": "Service degradation for Cable customers in Irrigon...", "area_label": "Irrigon", "cause_category": "fiber cut", "affected_band": "100-250", "geo_center": [-119.49, 45.89], "radius_m": 10000.0 } ], "maintenances": [] } Top level: =================== ======================================================== ``as_of`` ISO 8601 UTC timestamp of the snapshot (informational). ``status_summary`` Overall status word (informational, not mirrored). ``outages`` List of outage entries (mirrored as *outage* notices). ``maintenances`` List of maintenance entries (mirrored as *information* notices). Same entry shape as outages. =================== ======================================================== Per entry: =================== ======================================================== ``id`` **Required.** Stable unique identifier (string). ``public_text`` **Required.** Customer-facing description; shown to support staff as the notice body (Markdown rendered). ``status`` Free-form status word. ``resolved``, ``completed``, ``cancelled``/``canceled`` or ``closed`` resolve the mirrored notice; anything else means open. ``started_at`` ISO 8601 UTC start time → notice start date. ``etr`` ISO 8601 UTC estimated time to resolution → notice ETR/expiration. ``null`` = unknown ETR: the notice is marked "unknown expiration" with a provisional 3-day visibility window that renews while the event stays open (outages only; maintenances are exempt). ``area_label`` Optional human-readable area; used in the notice subject and details. ``cause_category`` Optional cause; used in subject/details. ``affected_band`` Optional affected-subscriber estimate; shown in the notice details. ``geo_center`` Optional ``[longitude, latitude]``; shown in details when no ``area_label`` is given. ``radius_m`` Optional radius in meters around ``geo_center``. =================== ======================================================== Notes ----- * All timestamps are interpreted as UTC (timestamps without an offset are assumed UTC) and converted to the tracker's local time. Feeds that mislabel local wall-clock times with a ``Z`` suffix can be accommodated tracker-side with the per-feed "Feed Timezone Override" setting, but emitting real UTC is strongly preferred. * An unresolved entry whose ETR has already passed is shown as "Unknown ETR" (with the stated ETR kept in the body) so the still-open event remains visible — keep ``etr`` updated as estimates slip. * Notice subjects are derived as ``Outage: `` and truncated to 150 characters. * Individually malformed entries (e.g. missing ``id``) are skipped and logged; the rest of the feed still mirrors. * Reference implementation of this schema: Blue Mountain Internet's public outage API, the first feed this integration was built against.